/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Model;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

/**
 *
 * @author snowangelic
 */
public class Kmeans extends Clusterization {

    public boolean normalized;
    public Distance distance;
    public ArrayList<Weight> weightList;

    Kmeans(KmeansOptions kOpt){
        Clusterization(kOpt);
        this.weightList=kOpt.getWeightList();
        this.normalized=kOpt.getNormalized();
        this.distance=kOpt.getDistance();
        compute();
    }

    public void compute(){
        // --- 1: Normaliser les données ---
        Preprocessor prec=new Preprocessor(dataSet);
        prec.normalize();

        // --- 2: Initialiser les clusters ---
            /* Chaque cluster recoit une action différente 
            et il compie sa position sur cette action */
        Iterator it=clusterList.iterator();
        ArrayList<Integer> randomList=new ArrayList<Integer>();
        while(it.hasNext()){
            Cluster currentCluster=(Cluster) it.next();
            boolean found=false;
            do{
                int index=(int) (Math.random() * (dataSet.getActionNbr()-1));
                if(randomList.contains(index)==false){
                    randomList.add(index);
                    currentCluster.addAction(dataSet.getAction(index));
                    currentCluster.recomputePosition();
                    found=true;
                }
            }while(found==false);
        }



        int[] prevState=new int[dataSet.getActionNbr()];
        int[] curState=new int[dataSet.getActionNbr()];
        do{
            
            for(int i=0;i<dataSet.getActionNbr();i++){
                prevState[i]=curState[i];
            }

            // --- 3: On associe chaque Action au cluster dont le centroide ets le plus proche
            for(int i=0;i<dataSet.getActionNbr();i++){
                int nearestCluster=0;
                float dist=Float.MAX_VALUE;
                for(int j=0;j<clusterList.size();j++){
                    if(clusterList.get(j).getDistance(dataSet.getAction(i),weightList,normalized,distance)<dist){
                        nearestCluster=j;
                        dist=clusterList.get(j).getDistance(dataSet.getAction(i),weightList,normalized,distance);
                    }
                    clusterList.get(j).removeAction(dataSet.getAction(i));
                }
                curState[i]=nearestCluster;
                clusterList.get(nearestCluster).addAction(dataSet.getAction(i));
            }

            // --- 4: On recalcul la position de chaque Cluster
            for(int i=0;i<clusterList.size();i++){
                clusterList.get(i).recomputePosition();
            }


            // Opération 3 et 4 à effectuer tant que les centroides ne sont pas a leur place défninitive
        }while(stateChanged(prevState,curState));
    }

    private boolean stateChanged(int[] prevState, int[] curState){
        boolean changed=false;
        for(int i=0;i<prevState.length;i++){
            if(prevState[i]!=curState[i]){
                changed=true;
                break;
            }
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //String command=br.readLine();

        return changed;
    }


    public ArrayList<Weight> getWeightList() {
        return weightList;
    }

    public Distance getDistance() {
        return distance;
    }

    public boolean getNormalized() {
        return normalized;
    }

    public void AddWeight(Attribute attribute,float weightVal){
        Weight weight=new Weight(attribute,weightVal);
        weightList.add(weight);
    }

   
}


